public with sharing class SearchPlanDocumentsVF{
  
    String status = '';
    String roles = '';
    List<Sales_Contract__c> contracts = null; 
      
    String userProfileName = '';
    UserRole[] currentUserSubDetails = null;
    Profile[] p = null;
    private Date effStartDate = null;
    private Date effEndDate = null;
    Map<ID, UserRole> uRoleMap = new Map<ID, UserRole>();
    Map<ID, UserRole> tempRoleMap = new Map<ID, UserRole>();
    Map<ID, UserRole> temp2RoleMap = new Map<ID, UserRole>();
    static String testVar = '';
    public Boolean displayFlag {get; set;}
    public Boolean isAdmin {get; set;}
    public Boolean isEndUser {get; set;}
    public Plan_Document_Inquiry__c pdi {get; set;}
    public Sales_Contract__c planDocument  {get; set;}
    public Boolean isNonMergeSearch {get; set;}    
    public Boolean isMergeSearch {get; set;}    
    private DataAccessControlUtil dacu = null;
    private Map<String, Schema.SObjectField> scSObjectFieldMap = new Map<String, Schema.SObjectField>(); 
    private String constructSoql {get; set;}
    
    public SearchPlanDocumentsVF()
    {
        Boolean hasPlanDocEDPermission;
        planDocument = new Sales_Contract__c();
        pdi = new Plan_Document_Inquiry__c();
        
        status = 'select';
        currentUserSubDetails = new List<UserRole>();
        
        isAdmin = isEndUser = displayFlag = isMergeSearch = isNonMergeSearch = false;
        URL__c[] urlList = [select Plan_Doc_Type__c from URL__c limit 1];
        if(urlList.size() > 0 && urlList[0].Plan_Doc_Type__c == 'no')
        {
            isNonMergeSearch = !isNonMergeSearch;
        }//end of if(urlList.size() > 0 && urlList[0].Plan_Doc_Type__c == 'no')
        else
        {
            isMergeSearch = !isMergeSearch;
        }
        
        
        for(UserRole[] roleList : [Select id, name, parentroleid from UserRole ur Where ur.ParentRoleId = :UserInfo.getUserRoleId() order by name])
            for(UserRole role: roleList)
            {
                currentUserSubDetails.add(role);
                tempRoleMap.put(role.Id, role);
                uRoleMap.put(role.Id, role);
            }

        while(tempRoleMap.size() > 0 && Limits.getQueries() < 95) 
        {
            if(currentUserSubDetails.size() == 1000)
                break;
            temp2RoleMap = tempRoleMap.deepClone();
            tempRoleMap.clear();
            tempRoleMap = getRolesAtDeeperLevel(temp2RoleMap);
        }

        if(currentUserSubDetails.size() > 0)
            setCurrentUserSub(currentUserSubDetails);

        Schema.DescribeSObjectResult pdPermission = Sales_Contract__c.SObjectType.getDescribe();
        if(pdPermission.isUpdateable() == true && pdPermission.isDeletable() == true && pdPermission.isCreateable() == true)
            hasPlanDocEDPermission = true;
        else
            hasPlanDocEDPermission = false;

        if(hasPlanDocEDPermission)
            isAdmin = !isAdmin;
        else
            isEndUser = !isEndUser;
            
        getDisplayColumns();
        
        User[] us = [select Id, ProfileId, Title from User u where u.Id = :UserInfo.getUserId()];
        if(us.size() > 0)
        {
            if(isAdmin == true && ApexPages.currentPage().getParameters().get('ur') == null)
                planDocument.User_ID__c = UserInfo.getUserId();
            else if(isAdmin == true && ApexPages.currentPage().getParameters().get('ur') != '')
                planDocument.User_ID__c = ApexPages.currentPage().getParameters().get('ur');
            
            if(isEndUser == true && ApexPages.currentPage().getParameters().get('ur') == null)
                pdi.User__c = UserInfo.getUserId();
            else if(isEndUser == true && ApexPages.currentPage().getParameters().get('ur') != '')
                pdi.User__c = ApexPages.currentPage().getParameters().get('ur');

            if(ApexPages.currentPage().getParameters().get('pg') != null && ApexPages.currentPage().getParameters().get('pg') != '')                
                planDocument.Batch__c = ApexPages.currentPage().getParameters().get('pg');
            
            if(ApexPages.currentPage().getParameters().get('ss') != null && ApexPages.currentPage().getParameters().get('ss') != '')
                status = ApexPages.currentPage().getParameters().get('ss');
            
            if(ApexPages.currentPage().getParameters().get('tp') != null && ApexPages.currentPage().getParameters().get('tp') != '')
                planDocument.Template__c = ApexPages.currentPage().getParameters().get('tp');
            
            if(ApexPages.currentPage().getParameters().get('rl') != null && ApexPages.currentPage().getParameters().get('rl') != '')
                roles = ApexPages.currentPage().getParameters().get('rl');
        }
    }
    
    private Map<ID, UserRole> getRolesAtDeeperLevel(Map<ID, UserRole> temp2RoleMap)
    {
        for(UserRole[] roleList : [select id, name, ParentRoleId from UserRole where ParentRoleId in : temp2RoleMap.keyset() order by name])
        {
            for(UserRole role: roleList)
            {
                if(currentUserSubDetails.size() == 1000)
                    break;
            
                currentUserSubDetails.add(role);

                tempRoleMap.put(role.Id, role);
                uRoleMap.put(role.Id, role);
            }
            if(currentUserSubDetails.size() == 1000)
                break;
         }
        return tempRoleMap;
    }
    
    
    /**
     * Used to display columns Template, Plan Group Name if User is an Admin
     * Hide the columns if User is an End User
    */
    public void getDisplayColumns()
    {
        Schema.DescribeSObjectResult tPermission = Template__c.SObjectType.getDescribe();
        if(tPermission.isCreateable() && tPermission.isDeletable() == true && tPermission.isCreateable() == true)
            displayFlag = true;
    }
    
    public void setCurrentUserSub(UserRole[] cUser)
    {
        if(cUser != null && cUser.size() > 0)
            currentUserSubDetails = cUser;
    }
    
    public UserRole[] getCurrentUserSub()
    {
        if(currentUserSubDetails != null && currentUserSubDetails.size() > 0)
            return currentUserSubDetails;
        else
            return null;
    }
    
    public void setUserProfileName(String name)
    {
        userProfileName = name;
    }
    
    public String getUserProfileName()
    {
        return userProfileName;
    }
    
    public List<SelectOption> getRolesList() {
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('select','Select'));
        if(!isAdmin)
        {
            User[] u = [select UserRoleId, UserRole.Name from User where Id = :UserInfo.getUserId()];
            if(u.size() > 0)
            {
                options.add(new SelectOption(u[0].UserRoleId, u[0].UserRole.Name));
            }

            UserRole cU = null;
            if(currentUserSubDetails != null)
            {
                for(Integer i=0;i<currentUserSubDetails.size(); i++)
                {
                    cU = currentUserSubDetails[i];
                    options.add(new SelectOption(cU.Id,cU.Name));
                    if(options.size() == 1000)
                        break;
                }
            }
        }
        else
        {
            for(UserRole[] userRole : [select Id, Name from UserRole order by Name limit 1000])
            {
                for(UserRole ur : userRole)
                {
                    options.add(new SelectOption(ur.Id,ur.Name));
                    
                    if(options.size() == 1000)
                        break;
                }
                if(options.size() == 1000)
                    break;
            }
        }
        return options;
    }
  
    public String getRoles() 
    {
        return roles;
    }
  
    public void setRoles(String roles) {
        this.roles = roles;
    }

    public List<SelectOption> getStatusList() 
    {
        List<SelectOption> options = new List<SelectOption>();
        options.add(new SelectOption('select','Select'));
        //Display the below two status only if User is Admin.
        if(displayFlag == true || isAdmin == true)
        {
            options.add(new SelectOption('Draft','Draft'));
        }
        options.add(new SelectOption('Distributed','Distributed'));
        options.add(new SelectOption('Published','Published'));
        options.add(new SelectOption('Viewed','Viewed'));
        options.add(new SelectOption('Accepted','Accepted'));
        options.add(new SelectOption('Rejected','Rejected'));
        options.add(new SelectOption('Plan Approved%','Manager Approved'));
        options.add(new SelectOption('Plan Rejected%','Manager Rejected'));
        options.add(new SelectOption('Inquiry Submitted','Inquiry Submitted'));
        options.add(new SelectOption('Inquiry Approved','Inquiry Approved'));
        options.add(new SelectOption('Inquiry Rejected','Inquiry Rejected'));
        options.add(new SelectOption('Submitted to Field Ops','Submitted to Field Ops'));
    //    options.add(new SelectOption('Reviewed','Reviewed'));

        return options;
    }//end of getStatusList

    public String getStatus()
    {
        if(status == null)
        {
             status = 'select';
        }

        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
  
    public Plan_Document_Inquiry__c getStartDate()
    {
        return pdi;
    }    

    public List<Sales_Contract__c> getContracts()
    {
        return contracts;
    }
    
    public void setContracts(List<Sales_Contract__c> contracts) {
        this.contracts = contracts;
    }
    
    public PageReference doSearch()
    {
        dacu = new DataAccessControlUtil();
        
        SObject scObj = new Sales_Contract__c();
        String message = dacu.isUpdateableObjectByUser(scObj);
        Sales_Contract__c[] sContract = null;
        
        if(message.equalsIgnoreCase('success'))
        {       
            if(scSObjectFieldMap.isEmpty())
                scSObjectFieldMap = dacu.getFieldMap(scObj);
            
            String percentile = '%';
            ID userId;
            try
            {
                if(isAdmin)
                    userId = planDocument.User_ID__c;
                else
                    userId = pdi.User__c;
                
                String templateName = '%';
                ID batchId = planDocument.Batch__c;  
                Date startDate = pdi.Effective_Start_Date__c;
                Date endDate = pdi.Effective_End_Date__c;
                if(isAdmin)        
                    ApexPages.currentPage().getParameters().put('ur', planDocument.User_ID__c);
                if(isEndUser)
                    ApexPages.currentPage().getParameters().put('ur', pdi.User__c);
                
                ApexPages.currentPage().getParameters().put('rl', roles);
                ApexPages.currentPage().getParameters().put('pg', planDocument.Batch__c);
                ApexPages.currentPage().getParameters().put('tp', planDocument.Template__c);
                ApexPages.currentPage().getParameters().put('ss', status);
                
                String[] statusListEndUser = new String[]{'Distributed', 'Viewed', 'Published', 'Accepted', 'Rejected', 'Inquiry Submitted', 'Inquiry Approved', 'Inquiry Rejected', 'Reviewed', 'Submitted to Field Ops', 'Plan Approved by '+UserInfo.getFirstName()+' '+UserInfo.getLastName(), 'Plan Rejected by '+UserInfo.getFirstName()+' '+UserInfo.getLastName()};
        
                if(contracts != null)
                    contracts.clear();
                    
                Template__c[] templateList = [select name from template__c where id = :planDocument.Template__c];
                if(templateList.size() > 0)
                    templateName = templateList[0].name;
                    
                String formWhereClause = '';
                
                if(status != 'select')
                    formWhereClause += ' Status__c like :status ';
                else if(displayFlag)
                    formWhereClause += ' Status__c like :percentile ';
                else
                    formWhereClause += ' Status__c in :statusListEndUser ';
                
                if(roles != 'select')
                    formWhereClause += ' and UserRoleId__c = :roles ';
            
                if(isAdmin == true && planDocument.User_ID__c != null)
                    formWhereClause += ' and User_ID__c = :userId ';
        
                if(isEndUser == true && pdi.User__c != null)
                    formWhereClause += ' and User_ID__c = :userId ';
        
                if(displayFlag == true && planDocument.Template__c != null)
                    formWhereClause += ' and TemplateName__c like :templateName ';
                
                if(isMergeSearch)// && pdi.Effective_Start_Date__c != null)
                    formWhereClause += ' and Effective_Start_Date__c != null and Effective_Start_Date__c >= :startDate ';
        
                if(isMergeSearch)// && pdi.Effective_End_Date__c != null)
                    formWhereClause += ' and Effective_End_Date__c <= :endDate ';

                if(isNonMergeSearch)
                    formWhereClause += ' and Effective_Start_Date__c = null ';
        
                if(displayFlag == true && planDocument.Batch__c != null)
                    formWhereClause += ' and Batch__c = :batchId ';
    
                //system.debug('Form where Clause : '+formWhereClause+'   Batch : '+batchId+'  Status :'+status);
                String[] expectedFields = new String[]{'Id', 'Name', 'FirstName__c', 'LastName__c', 'Template__c', 'TemplateName__c', 'BatchName__c', 'Plan_Document_Name__c', 'Status__c', 'UserRoleName__c', 'Effective_Start_Date__c', 'Effective_End_Date__c', 'BatchID__c', 'UserID__c'}; 
                Set<String> allowedFields = dacu.getAccessibleFields(scObj, scSObjectFieldMap, expectedFields);

                if(!allowedFields.isEmpty())
                {
                    constructSoql = 'Select ';
                    for(String roField: allowedFields)
                    {
                        constructSoql += roField+', ';
                    }
                    constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
                    constructSoql += ' from Sales_Contract__c where '+formWhereClause+' order by createddate desc limit 51';
    
                    //contracts = Database.query('select Id, Name, FirstName__c, LastName__c, Template__c, TemplateName__c, BatchName__c, Plan_Document_Name__c, Status__c, UserRoleName__c, Effective_Start_Date__c, Effective_End_Date__c, BatchID__c, UserID__c from Sales_Contract__c where '+formWhereClause+' order by createddate desc limit 51');//order by CreatedDate Desc limit 101');
                    contracts = Database.query(constructSoql);
                    if(contracts != null && contracts.size() > 50)
                        ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, 'The search returned more than the maximum number of rows (50). Please refine your search criteria.'));
                    if(contracts != null && contracts.size() == 0)
                        contracts = null;
                }
                     
            }
            catch(Exception e)
            {
                ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, e.getMessage()));
            }   
        }
        return null;
    }
   
    static testMethod void testSearchPlanDocumentsVF() 
    {
        PageReference pg = Page.SearchPlanDocuments;
        
        Test.setCurrentPage(pg);

        testVar = 'test';
        SearchPlanDocumentsVF spvf = new SearchPlanDocumentsVF();
        if(spvf != null)
        {
            Template__c t = new Template__c(name = 'Test Search');
            insert t;
            Template__c[] tempT = [select name from Template__c where id = :t.id];
            system.assertEquals(t.name, tempT[0].name);
                         
            Batch__c b = new Batch__c(name = 'Test', Template__c = t.id, TemplateId__c = t.id);
            insert b;
            Batch__c[] batT = [select name, Template__c from Batch__c where id=:b.id];
            system.assertEquals(b.name, batT[0].name);
            system.assertEquals(b.Template__c, batT[0].Template__c);
            
            Sales_Contract__c sc = new Sales_Contract__c(BatchID__c = b.id, Template__c = t.id, TemplateName__c = t.name);
            insert sc;
            Sales_Contract__c[] scT = [select BatchID__c, Template__c from Sales_Contract__c where id=:sc.id];
            system.assertEquals(sc.BatchID__c, scT[0].BatchID__c);
            system.assertEquals(sc.Template__c, scT[0].Template__c);
            
            spvf.getDisplayColumns();
            spvf.setUserProfileName('System Administrator');
            system.assertEquals('System Administrator', spvf.getUserProfileName());
            spvf.getRolesList();
            spvf.setRoles(UserInfo.getUserRoleId());
            system.assertEquals(UserInfo.getUserRoleId(), spvf.getRoles());
    
            spvf.setUserProfileName('Western Sales Team');
            system.assertEquals('Western Sales Team', spvf.getUserProfileName());
            spvf.getRolesList();
            spvf.setRoles(Userinfo.getUserRoleId());
            system.assertEquals(UserInfo.getUserRoleId(), spvf.getRoles());
    
            List<SelectOption> options = new List<SelectOption>();
            options.add(new SelectOption('Distributed','Distributed'));
            options.add(new SelectOption('Submitted to Field Ops','Submitted to Field Ops'));
            system.assertEquals(options.get(options.size() - 1).getValue(), spvf.getStatusList().get(spvf.getStatusList().size() - 1).getValue());
            
            spvf.status = 'Published';
            system.assertEquals('Published', spvf.getStatus());
            
            spvf.setStatus('Published');
            
            spvf.setRoles(UserInfo.getUserRoleId());
            system.assertEquals(UserInfo.getUserRoleId(), spvf.getRoles());
            
            spvf.pdi = new Plan_Document_Inquiry__C();
            system.assertEquals(spvf.pdi, spvf.getStartDate());
            
            spvf.doSearch();
            system.assertEquals(null, spvf.doSearch());
            spvf.setUserProfileName('Western Sales Team');
            spvf.doSearch();
            system.assertEquals(null, spvf.doSearch());
            spvf.setUserProfileName('System Administrator');
            system.assertEquals(null, spvf.doSearch());
            spvf.doSearch();
            
            if(spvf.contracts != null)
                spvf.setContracts(spvf.contracts);
            system.assertEquals(spvf.contracts, spvf.getContracts());
            
        }    
    }
    
}//end of class